<?php

namespace App\Kuafu\CustomPayment\Service;

use App\Kuafu\Base\Model\BaseModel;
use App\Kuafu\Common\Service\CommonService;
use App\Kuafu\CustomPayment\Enum\CustomPaymentCodeEnum;
use App\Kuafu\CustomPayment\Enum\CustomPaymentEnum;
use App\Kuafu\CustomPayment\Enum\CustomPaymentShopMappingsEnum;
use App\Kuafu\CustomPayment\Exceptions\CustomPaymentException;
use App\Kuafu\CustomPayment\Model\CustomPaymentModel;
use App\Kuafu\CustomPayment\Model\CustomPaymentShopMappingsModel;
use App\Kuafu\Shop\Enum\ShopCacheEnum;
use App\Kuafu\Shop\Events\PaymentShopUpdateEvent;
use App\Library\Redis\RedisHelp;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Event;

/**
 *
 */
class CustomPaymentService extends BaseModel
{

    /**
     * 添加支付方式
     *
     * @param $requestParams
     * @param $uid
     * @throws CustomPaymentException
     */
    public static function add($requestParams, $uid)
    {
        try {
            CustomPaymentModel::insert(array_merge($requestParams, [
                'status'       => CustomPaymentEnum::STATUS_ON,
                'createdAt'    => time(),
                'createdByUid' => $uid
            ]));
        } catch (\Exception $exception) {
            throw new CustomPaymentException(CustomPaymentCodeEnum::ERR_ADD);
        }
    }


    /**
     * 添加支付方式
     *
     * @param $requestParams
     * @param $uid
     * @throws CustomPaymentException
     */
    public static function setStatus($requestParams, $uid)
    {
        try {
            DB::beginTransaction();
            CustomPaymentModel::query()->where('id', $requestParams['id'])->update(array_merge($requestParams, [
                'updatedAt'    => time(),
                'updatedByUid' => $uid
            ]));

            //取反状态受影响的门店
            $changeShopIds = CustomPaymentShopMappingsModel::query()
                                                           ->where('payId', $requestParams['id'])
                                                           ->where(
                                                               'status',
                                                               $requestParams['status'] == CustomPaymentShopMappingsEnum::STATUS_ON ?
                                                                   CustomPaymentShopMappingsEnum::STATUS_OFF : CustomPaymentShopMappingsEnum::STATUS_ON
                                                           )
                                                           ->pluck('shopId')
                                                           ->toArray();

            CustomPaymentShopMappingsModel::query()->where('payId', $requestParams['id'])->update([
                'status'       => $requestParams['status'],
                'updatedAt'    => time(),
                'updatedByUid' => $uid
            ]);

            event(new PaymentShopUpdateEvent($changeShopIds));
            DB::commit();
        } catch (\Exception $exception) {
            DB::rollBack();
            throw new CustomPaymentException(CustomPaymentCodeEnum::ERR_UPDATE);
        }
    }

    /**
     * 支付方式列表
     *
     * @param $name
     * @param $status
     * @return array|Builder[]
     */
    public static function getList($name, $status): array
    {
        return [
            'lists' => CustomPaymentModel::getList($name, $status)->map(function (CustomPaymentModel $v) {
                return [
                    'id'              => $v->id,
                    'name'            => $v->name,
                    'reckonType'      => $v->reckonType,
                    'isInvoice'       => $v->isInvoice,
                    'type'            => $v->type,
                    'status'          => $v->status,
                    'createdAt'       => $v->createdAt->timestamp > 0 ? date('Y-m-d H:i:s',
                        $v->createdAt->timestamp) : '',
                    'updatedAt'       => $v->updatedAt->timestamp > 0 ? date('Y-m-d H:i:s',
                        $v->updatedAt->timestamp) : '',
                    'createdUserName' => $v->createdByUidRel ? $v->createdByUidRel->username : '',
                    'updatedUserName' => $v->updatedByUidRel ? $v->updatedByUidRel->username : '',
                ];
            })->toArray()
        ];
    }

    /**
     * 支付方式下发
     *
     * @param $requestParams
     * @param $uid
     * @throws CustomPaymentException
     */
    public static function sendPayment($requestParams, $uid)
    {
        try {
            DB::beginTransaction();
            $insertData  = [];
            $baseQuery   = CustomPaymentShopMappingsModel::query()->where('payId', $requestParams['payId']);
            $existShpIds = (clone $baseQuery)->where('isDeleted', 0)
                                             ->where('status', CustomPaymentShopMappingsEnum::STATUS_ON)
                                             ->pluck('shopId')->toArray();
            (clone $baseQuery)->update([
                'isDeleted'    => 1,
                'createdAt'    => time(),
                'updatedByUid' => $uid
            ]);
            array_map(function ($v) use (&$insertData, $requestParams, $uid) {
                array_push($insertData, [
                    'createdByUid' => $uid,
                    'updatedByUid' => $uid,
                    'createdAt'    => time(),
                    'status'       => CustomPaymentShopMappingsEnum::STATUS_ON,
                    'shopId'       => $v,
                    'payId'        => $requestParams['payId'],
                ]);
            }, $requestParams['shopIds']);

            CustomPaymentShopMappingsModel::insert($insertData);

            $diffShopIds = array_diff($requestParams['shopIds'], $existShpIds);
            event(new PaymentShopUpdateEvent($diffShopIds));
            DB::commit();
        } catch (\Exception $e) {
            DB::rollBack();
            throw new CustomPaymentException(CustomPaymentCodeEnum::ERR_UPDATE);
        }
    }

    /**
     * 门店支付方式 启用｜禁用
     *
     * @param $requestParams
     * @param $uid
     * @throws CustomPaymentException
     */
    public static function setStatusShopPayment($requestParams, $uid)
    {
        try {
            $paymentShop = CustomPaymentShopMappingsModel::query()->where('id', $requestParams['id'])->first();
            CustomPaymentShopMappingsModel::query()->where('id', $requestParams['id'])
                                          ->update(array_merge($requestParams, [
                                              'updatedAt'    => time(),
                                              'updatedByUid' => $uid
                                          ]));
            event(new PaymentShopUpdateEvent([$paymentShop->shopId]));
        } catch (\Exception $exception) {
            throw new CustomPaymentException(CustomPaymentCodeEnum::ERR_UPDATE);
        }
    }

    /**
     * 门店支付方式列表
     *
     * @param $pageSize
     * @param $pageNum
     * @param $name
     * @param $shopId
     * @return array
     */
    public static function shopPaymentList($pageSize, $pageNum, $name, $shopId): array
    {
        $pagination = CustomPaymentShopMappingsModel::getLists($pageSize, $pageNum, $name, $shopId);
        return [
            'count'    => $pagination->total(),
            'lists'    => self::formatCustomPaymentShop($pagination->items()),
            'pageNum'  => $pageNum,
            'pageSize' => $pageSize
        ];
    }

    /**
     * 下发记录
     *
     * @param $pageSize
     * @param $pageNum
     * @param $name
     * @param $shopId
     * @param $startAt
     * @param $endAt
     * @return array
     */
    public static function sendPaymentHistory($pageSize, $pageNum, $name, $shopId, $startAt, $endAt): array
    {
        $pagination = CustomPaymentShopMappingsModel::getLists($pageSize, $pageNum, $name, $shopId, $startAt, $endAt,
            true, true);
        return [
            'count'    => $pagination->total(),
            'lists'    => self::formatCustomPaymentShop($pagination->items()),
            'pageNum'  => $pageNum,
            'pageSize' => $pageSize
        ];
    }

    /**
     * 格式化下发后数据记录
     *
     * @param array $data
     * @return array
     */
    public static function formatCustomPaymentShop(array $data): array
    {
        return array_map(function (CustomPaymentShopMappingsModel $v) {
            return [
                'id'              => $v->id,
                'status'          => $v->status,
                'isDeleted'       => $v->isDeleted,
                'shopId'          => $v->shopId,
                'name'            => $v->customPaymentRel ? $v->customPaymentRel->name : '',
                'type'            => $v->customPaymentRel ? $v->customPaymentRel->type : '',
                'reckonType'      => $v->customPaymentRel ? $v->customPaymentRel->reckonType : '',
                'isInvoice'       => $v->customPaymentRel ? $v->customPaymentRel->isInvoice : '',
                'createdAt'       => $v->createdAt->timestamp > 0 ? date('Y-m-d H:i:s',
                    $v->createdAt->timestamp) : '',
                'updatedAt'       => $v->updatedAt->timestamp > 0 ? date('Y-m-d H:i:s',
                    $v->updatedAt->timestamp) : '',
                'shopName'        => $v->relationLoaded('shopRel') && $v->shopRel ? $v->shopRel->name : '',
                'createdUserName' => $v->createdByUidRel ? $v->createdByUidRel->username : '',
                'updatedUserName' => $v->updatedByUidRel ? $v->updatedByUidRel->username : '',
            ];
        }, $data);
    }


    /**
     * 获取支付方式已下发门店列表
     *
     * @param $requestParams
     * @return array
     */
    public static function getPaymentShop($requestParams): array
    {
        return [
            'shopIds' => CustomPaymentShopMappingsModel::query()->where('payId', $requestParams['payId'])
//                                                       ->where('status', CustomPaymentShopMappingsEnum::STATUS_ON)
                                                       ->pluck('shopId')
                                                       ->toArray()
        ];
    }


    /**
     * 获取自定义支付门店可用列表
     *
     * @param $shopId
     * @return array
     */
    public static function enableCustomPaymentLists($shopId): array
    {
        $customPaymentLists = RedisHelp::getInstance()->remember(
            ShopCacheEnum::getShopCustomPayment($shopId),
            24 * 60 * 60,
            function () use ($shopId) {
                return CustomPaymentModel::query()
                                         ->where(function ($query) use ($shopId) {
                                             $query->where('type', '=', CustomPaymentEnum::TYPE_DEFAULT)
                                                   ->orWhereHas('customPaymentShopRel',
                                                       function ($query) use ($shopId) {
                                                           $query->where('status',
                                                               CustomPaymentShopMappingsEnum::STATUS_ON)
                                                                 ->where('shopId', $shopId);
                                                       });
                                         })
                                         ->get()->sortByDesc('type')->sortBy('createdAt')
                                         ->map(function ($v) use ($shopId) {
                                             return [
                                                 'payId'      => $v->id,
                                                 'name'       => $v->name,
                                                 'shopId'     => $shopId,
                                                 'type'       => $v->type,
                                                 'reckonType' => $v->reckonType,
                                                 'isInvoice'  => $v->isInvoice,
                                                 'status'     => $v->status,
                                                 'isShow'     => $v->isShow
                                             ];
                                         })->values()->toJson(JSON_UNESCAPED_UNICODE);
            },
            function ($value) {
                return json_decode($value, true);
            }
        );

        return [
            'customPaymentLists' => $customPaymentLists
        ];
    }
}
